﻿#include "CommandHandler.h"
#include "strTool.h"
using namespace strtool;

CommandHandler::CommandHandler( string _inPath, string _outPath, string _fn)
{
	inPath = _inPath;
	outPath = _outPath;
	fn = _fn;
}

void CommandHandler::open()
{
	fin.open(inPath+fn+".dec",ios::in|ios::binary|ios::_Nocreate);
	fout.open(outPath+fn+".txt",ios::out|ios::binary);
	//假设打开成功，不成功无视
	assert(fin.is_open() && fout.is_open());
	mode = NONE;
	visChoice = visSwitch = 0;

}
//一些正则，我都不想看第二遍 =W= 
static regex test("\\[(\\S*?)\\]\\s*(\\S*?):\\s*(.*)");//判断最基本的[00001cb4] 20: unknown20 47
static regex isChoice("\\{clearText 0\\}\\s*\\{choice\\s*.*?\\|.*");//提取 道歉 | 妳才是在做什麼呢 | 沉默
static regex isChoiceId("(choiceId) (.*) (.*)");//[0000005e] 1a: choiceId 1203 113
static regex isSwitch("switch_varop \\(.*?\\) (.*) .*? \\(.*\\)");//判断真实switch的开始"switch_varop (28 0a a4) b3 0014 (00)",
static regex getLabel("\\d+\\s+->\\s(\\d+)\\s+(.*)\\s+\\(.*\\)");//获取label,"27 -> 2 0000171d (0000000d)",
static regex isGotoif("gotoif\\s+\\d+\\s+\\(.*\\)\\s+(.*?) (.*) \\(.*\\)\\s+(.*?)\\s+.*-> (.*?) \\(.*\\)");//gotoif 1 (28 0a a4) b3 == (01) 1 (0001) -> 0000104c (0000000b)
static regex isVarop("varop \\(.*\\) (.*) (.*) \\(.*\\) (.*)");//varop (28 0a a4) b1 := (00) 2
static regex isEnd("end");
static regex isGoto("goto (.*?) \\(.*\\)");//goto 00000ddb (00000025)
static regex isJump("jump (.*)");//jump SC2F
static regex isCond(".*\\{cond.*?\\}(.*)");//cond (28 0a a4) d0 14 (00)}旋轉海豚
static regex isSound("\\{sound (.*?)\\}(.*)");//{sound EOP003}{clearText 0}【武】 「你……你好……」 
static regex isText("\\{clearText 0\\}(.*)");

string CommandHandler::procLine(string s,int lineNum)
{
	//如果当前没有在模式中的话，可能是任意的字符串，但是不管
	cmatch result,cc;
	bool is;
	string ret = s;
	string addon = "";

	is = regex_search(s.c_str(),result,test);
	if (lineNum == 1)
	{
		addon = "*L" + fn + "\n";
	}
	if (is && (lineNum == 1 || sJumpLabel.find(result[1]) != sJumpLabel.end()) )
	{
		string t = result[1];
		addon +=  "*L"+ fn+"_"+t +"\n";
	}
	if (is && (mode != SWITCH ))//如果匹配到了[XXXXXXXXX]
	{
		string t = result[3];
		if (!strncmp(t.c_str(),"text",4))
		{
			mode = TEXT;
			ret = "";
		}
		else if (regex_search(s.c_str(),result,isChoiceId)){//生成choiceID
			
			choiceID = "*L";
			t = result[1];
			choiceID += t;
			t = result[2];
			choiceID = choiceID + "_" + t;
			t = result[3];
			choiceID = choiceID + "_" + t;
			return "";
		}
		else {
			ret = procCmd(t);
		}
	}
	else {
		is = regex_search(s.c_str(),result,isSwitch);
		if (is)
		{
			oper = result[1];
			if (mode != FINISH_CHOICE)
			{
				mode = SWITCH;
			}
			
			visSwitch = 1;
			return "";
		}
		if (mode == TEXT)
		{
			string t;
			is = regex_search(s.c_str(),result,isChoice);
			if (!is)
			{
				ret = procText(s);
			} 
			else
			{
				//标志CHOICE模式开始
				mode = CHOICE;
				
				visChoice = 1;
				visSwitch = 0;
				t = s;
				if (regex_search(t.c_str(),cc,isCond))//处理Cond
				{
					t = cc[1];
					option.push_back(t);
				}
				ret = "";
			}
		}
		else if (mode == CHOICE){//获取每个choice
			string t;
			if (s == "|")
			{
				return "";
			}
			else if (s == "}"){
				mode = FINISH_CHOICE;//选项分离完毕，进入FINISH_CHOICE模式
				return "";
			}
			t = s;
			if (regex_search(t.c_str(),cc,isCond))//处理Cond
			{
				t = cc[1];
			}
			option.push_back(t);
			return "";
			
		}
		else if (mode == FINISH_CHOICE || mode == SWITCH)
		{
			//
			//switch和choice还是有区别的，有时候可能没有switch也是可能的。所以两个功能要分开。
			//详细一点，choice后面一定会跟一个switch，不过那个switch的决定值由choice决定
			//在没有choice的情况下，就是单判断变量了。
			//不过如果是choice的话，必须是choice->switch
			if (!visSwitch)
			{
				is = regex_search(s.c_str(),result,isSwitch);
				if (is)
				{
					visSwitch = 1;
					oper = result[1];
				}
				ret =  "";
			} 
			else 
			{
				is = regex_search(s.c_str(),result,getLabel);
				if (is)
				{
					jumpLabel.push_back(result[2]);
					jumpVar.push_back(result[1]);
					ret = "";
				} 
				else if (mode == FINISH_CHOICE)
				{
					visSwitch = 0;
					mode = NONE;
					 ret = "csel ";
					for (int i = 0; i < min(option.size(),jumpLabel.size()); i++)
					{
						if (i != 0)
							ret += ",";
						ret += "\""+option[i]+"\", "+"*L_pre_"+ fn+"_"+jumpLabel[i];
					}
					for (int i = 0; i < min(option.size(),jumpLabel.size()); i++)//转跳后修改值,然后转跳到公共choice
					{
						ret =ret + "\n"+"*L_pre_"+ fn+"_"+jumpLabel[i]+"\n"+" mov %V_"+oper+", "+jumpVar[i]+"\n goto "+choiceID+"\n";
					}
					ret += "\n";
					ret += choiceID;
					for (int i = 0; i < min(option.size(),jumpLabel.size()); i++)//转跳到jumpLabel
					{
						ret = ret + "\n"+"if %V_"+oper+" == "+jumpVar[i]+" goto "+"*L"+ fn+"_"+jumpLabel[i]+"\n";
					}
					if (option.size() == 0)
					{
						ret = "";
					}
					option.clear();
					jumpLabel.clear();
					jumpVar.clear();
					 
				}
				else if (mode == SWITCH){
					visSwitch = 0;
					mode = NONE;
					for (int i = 0; i < jumpLabel.size(); i++)//转跳后修改值后转跳到真实地址
					{
						ret = ret + "\n"+"if %V_"+oper+" == "+jumpVar[i]+" goto "+"*L"+ fn+"_"+jumpLabel[i]+"\n";
					}
					option.clear();
					jumpLabel.clear();
					jumpVar.clear();
				}
			}
		}
	}
	return addon+ret;
}

bool CommandHandler::reachEOF()
{
	if (fin.eof())
	{
		return true;
	}
	else return false;
}

std::string CommandHandler::getline()
{
	char str[2048];
	 fin.getline(str,2048);
	 return str;
}

CommandHandler::~CommandHandler()
{
	fin.close();
	fout.close();
}

void CommandHandler::putline( string s )
{
	if (s.size() == 0)
	{
		return;
	}
	fout<<s<<endl;
}
//gotoif 1 (28 0a a4) b3 == (01) 1 (0001) -> 0000104c (0000000b)
std::string CommandHandler::procCmd( string s )
{
	string ret = s,t;
	cmatch result,cc;
	bool is;
	is = regex_match(s.c_str(),isEnd);
	if (is)
	{
		return "";
	}
	is = regex_search(s.c_str(),result,isGotoif);
	if (is)//gotoif
	{
		t = result[1];
		ret = "if  %V_"+t+" ";
		t = result[2];
		ret += t + " ";
		t = result[3];
		if (isD(t))
		{
			ret += t+" ";
		} 
		else
		{
			ret += "%V_"+t+" ";
		}
		t = result[4];
		ret += "    goto *L"+fn+"_"+t+"\n";
	} 
	else
	{//varop (28 0a a4) b1 := (00) 2
		is = regex_search(s.c_str(),result,isVarop);
		if (is)
		{
			string op = result[2];
			string s1,s3;
			s1 = result[1];
			s3 = result[3];
			ret = "";
			usedOp.insert("V_"+s1);
			if (op == ":=")
			{
				ret = "mov %V_"+s1+", ";
			} 
			else if(op == "+=")
			{
				ret = "add %V_"+s1+", ";
			}
			else if (op == "-=")
			{
				ret = "sub %V_"+s1+", ";
			}
			if (isD(s3))
			{
				ret += s3;
			}
			else {
				ret += "%V_"+s3;
				usedOp.insert("V_"+s3);
			}
			ret += "\n";
		}
		else if (regex_search(s.c_str(),result,isGoto))
		{
			string s1 = result[1];
			ret = "goto *L"+ fn+"_"+s1;
		}
		else if (regex_search(s.c_str(),result,isJump))
		{
			string s1 = result[1];
			ret = "goto *L"+getLow(s1);
		}

	}
	return ret;
}


bool CommandHandler::isD( string s )
{
	for (int i = 0; i < s.length(); i++)
	{
		if (!isdigit(s[i]))
		{
			return false;
		}
	}
	 return true;
}

std::string CommandHandler::getLow( string s )
{
	string ret;
	for (int i = 0; i < s.length(); i++)
	{
		ret += tolower(s[i]);
	}
	return ret;
}

std::string CommandHandler::procText( string s )
{
	string ret,t;
	cmatch result,cc;
	bool is = 0;
	if (s.size() == 0)
	{
		return "";
	}
	if (regex_search(s.c_str(),result,isSound))
	{
		t = result[1];
		ret = "["+getLow(t);
		s = result[2];
	}
	else ret += "[NONE";
	if (regex_search(s.c_str(),result,isText)){
		t = result[1];
		ret += "|1]";
		ret += t;
	}
	else {
		ret += "|0]";
		ret += s;
	}
	
	return ret;
}


